package com.dm.cloud.databases.mutimysql;

import lombok.extern.log4j.Log4j2;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * @ ClassName: DataSourceAspect
 * @ Description: AOP数据源切换
 */
@Aspect
@Order(2)
@Component
@Log4j2
public class DataSourceAspect {

    // 切入点
//    @Pointcut("execution(* com.dm.cloud.api.service.*Service..*(..))")
    @Pointcut("execution(* com.dm.cloud.service.*Service..*(..))")
    public void dataSourcePointCut(){
        //引入切点
    }

    /**
     * 方法前执行切换
     * @param joinPoint
     */
    @Before("dataSourcePointCut()")
    private void before(JoinPoint joinPoint){

        Object[] args = joinPoint.getArgs(); // 参数值
        String[] argNames = ((MethodSignature)joinPoint.getSignature()).getParameterNames(); // 参数名
        //参数名和参数值的位置是一一对应的
        int targetPos = -1 ;
        for(int i=0;i<argNames.length;i++){
            /**
             * 这里主要是通过获取方法中的 db参数来获取目标数据源
             * 因此在如果想要切换数据源就必须在切片方法上 增加该参数 否则使用默认数据源
             */
            if("db".equals(argNames[i])){
                targetPos=i;
                break;
            }
        }
        try {
            if(targetPos>=0){
                //动态切换
                JdbcContextHolder.putDataSource(args[targetPos].toString());
            }else{
                //没设置数据源信息 使用默认数据源
                log.info(">>> current thread " + Thread.currentThread().getName() + " is working with default database");
            }
        }catch (Exception e){
            log.error("change database error: "+e.getMessage());
        }
    }

    /**
     * 执行完切面后，将线程共享中的数据源名称清空
     * @param joinPoint
     */
    @After("dataSourcePointCut()")
    public void after(JoinPoint joinPoint){
        log.info(">>> datasource dispose");
        JdbcContextHolder.removeDataSource();
    }

}